1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package com.sun.imageio.plugins.bmp;
27
28 import java.awt.Point;
29 import java.awt.Rectangle;
30 import java.awt.Transparency;
31 import java.awt.color.ColorSpace;
32 import java.awt.color.ICC_ColorSpace;
33 import java.awt.color.ICC_Profile;
34 import java.awt.image.BufferedImage;
35 import java.awt.image.ColorModel;
36 import java.awt.image.ComponentColorModel;
37 import java.awt.image.ComponentSampleModel;
38 import java.awt.image.DataBuffer;
39 import java.awt.image.DataBufferByte;
40 import java.awt.image.DataBufferInt;
41 import java.awt.image.DataBufferUShort;
42 import java.awt.image.DirectColorModel;
43 import java.awt.image.IndexColorModel;
44 import java.awt.image.MultiPixelPackedSampleModel;
45 import java.awt.image.PixelInterleavedSampleModel;
46 import java.awt.image.Raster;
47 import java.awt.image.SampleModel;
48 import java.awt.image.SinglePixelPackedSampleModel;
49 import java.awt.image.WritableRaster;
50
51 import javax.imageio.IIOException;
52 import javax.imageio.ImageIO;
53 import javax.imageio.ImageReader;
54 import javax.imageio.ImageReadParam;
55 import javax.imageio.ImageTypeSpecifier;
56 import javax.imageio.metadata.IIOMetadata;
57 import javax.imageio.spi.ImageReaderSpi;
58 import javax.imageio.stream.ImageInputStream;
59 import javax.imageio.event.IIOReadProgressListener;
60 import javax.imageio.event.IIOReadUpdateListener;
61 import javax.imageio.event.IIOReadWarningListener;
62
63 import java.io.*;
64 import java.nio.*;
65 import java.security.AccessController;
66 import java.security.PrivilegedAction;
67 import java.util.ArrayList;
68 import java.util.Iterator;
69 import java.util.StringTokenizer;
70
71 import com.sun.imageio.plugins.common.ImageUtil;
72 import com.sun.imageio.plugins.common.I18N;
73
74
75
76
77
78
79
80
81
82 public class BMPImageReader extends ImageReader implements BMPConstants {
83
84 private static final int VERSION_2_1_BIT = 0;
85 private static final int VERSION_2_4_BIT = 1;
86 private static final int VERSION_2_8_BIT = 2;
87 private static final int VERSION_2_24_BIT = 3;
88
89 private static final int VERSION_3_1_BIT = 4;
90 private static final int VERSION_3_4_BIT = 5;
91 private static final int VERSION_3_8_BIT = 6;
92 private static final int VERSION_3_24_BIT = 7;
93
94 private static final int VERSION_3_NT_16_BIT = 8;
95 private static final int VERSION_3_NT_32_BIT = 9;
96
97 private static final int VERSION_4_1_BIT = 10;
98 private static final int VERSION_4_4_BIT = 11;
99 private static final int VERSION_4_8_BIT = 12;
100 private static final int VERSION_4_16_BIT = 13;
101 private static final int VERSION_4_24_BIT = 14;
102 private static final int VERSION_4_32_BIT = 15;
103
104 private static final int VERSION_3_XP_EMBEDDED = 16;
105 private static final int VERSION_4_XP_EMBEDDED = 17;
106 private static final int VERSION_5_XP_EMBEDDED = 18;
107
108
109 private long bitmapFileSize;
110 private long bitmapOffset;
111 private long compression;
112 private long imageSize;
113 private byte palette[];
114 private int imageType;
115 private int numBands;
116 private boolean isBottomUp;
117 private int bitsPerPixel;
118 private int redMask, greenMask, blueMask, alphaMask;
119
120 private SampleModel sampleModel, originalSampleModel;
121 private ColorModel colorModel, originalColorModel;
122
123
124 private ImageInputStream iis = null;
125
126
127 private boolean gotHeader = false;
128
129
130 private int width;
131
132
133 private int height;
134
135
136 private Rectangle destinationRegion;
137
138
139 private Rectangle sourceRegion;
140
141
142 private BMPMetadata metadata;
143
144
145 private BufferedImage bi;
146
147
148
149
150 private boolean noTransform = true;
151
152
153 private boolean seleBand = false;
154
155
156 private int scaleX, scaleY;
157
158
159 private int[] sourceBands, destBands;
160
161
162
163
164 public BMPImageReader(ImageReaderSpi originator) {
165 super(originator);
166 }
167
168
169 public void setInput(Object input,
170 boolean seekForwardOnly,
171 boolean ignoreMetadata) {
172 super.setInput(input, seekForwardOnly, ignoreMetadata);
173 iis = (ImageInputStream) input;
174 if(iis != null)
175 iis.setByteOrder(ByteOrder.LITTLE_ENDIAN);
176 resetHeaderInfo();
177 }
178
179
180 public int getNumImages(boolean allowSearch) throws IOException {
181 if (iis == null) {
182 throw new IllegalStateException(I18N.getString("GetNumImages0"));
183 }
184 if (seekForwardOnly && allowSearch) {
185 throw new IllegalStateException(I18N.getString("GetNumImages1"));
186 }
187 return 1;
188 }
189
190 public int getWidth(int imageIndex) throws IOException {
191 checkIndex(imageIndex);
192 readHeader();
193 return width;
194 }
195
196 public int getHeight(int imageIndex) throws IOException {
197 checkIndex(imageIndex);
198 readHeader();
199 return height;
200 }
201
202 private void checkIndex(int imageIndex) {
203 if (imageIndex != 0) {
204 throw new IndexOutOfBoundsException(I18N.getString("BMPImageReader0"));
205 }
206 }
207
208 public void readHeader() throws IOException {
209 if (gotHeader)
210 return;
211
212 if (iis == null) {
213 throw new IllegalStateException("Input source not set!");
214 }
215 int profileData = 0, profileSize = 0;
216
217 this.metadata = new BMPMetadata();
218 iis.mark();
219
220
221 byte[] marker = new byte[2];
222 iis.read(marker);
223 if (marker[0] != 0x42 || marker[1] != 0x4d)
224 throw new IllegalArgumentException(I18N.getString("BMPImageReader1"));
225
226
227 bitmapFileSize = iis.readUnsignedInt();
228
229 iis.skipBytes(4);
230
231
232 bitmapOffset = iis.readUnsignedInt();
233
234
235
236 long size = iis.readUnsignedInt();
237
238 if (size == 12) {
239 width = iis.readShort();
240 height = iis.readShort();
241 } else {
242 width = iis.readInt();
243 height = iis.readInt();
244 }
245
246 metadata.width = width;
247 metadata.height = height;
248
249 int planes = iis.readUnsignedShort();
250 bitsPerPixel = iis.readUnsignedShort();
251
252
253 metadata.bitsPerPixel = (short)bitsPerPixel;
254
255
256
257 numBands = 3;
258
259 if (size == 12) {
260
261 metadata.bmpVersion = VERSION_2;
262
263
264 if (bitsPerPixel == 1) {
265 imageType = VERSION_2_1_BIT;
266 } else if (bitsPerPixel == 4) {
267 imageType = VERSION_2_4_BIT;
268 } else if (bitsPerPixel == 8) {
269 imageType = VERSION_2_8_BIT;
270 } else if (bitsPerPixel == 24) {
271 imageType = VERSION_2_24_BIT;
272 }
273
274
275 int numberOfEntries = (int)((bitmapOffset - 14 - size) / 3);
276 int sizeOfPalette = numberOfEntries*3;
277 palette = new byte[sizeOfPalette];
278 iis.readFully(palette, 0, sizeOfPalette);
279 metadata.palette = palette;
280 metadata.paletteSize = numberOfEntries;
281 } else {
282 compression = iis.readUnsignedInt();
283 imageSize = iis.readUnsignedInt();
284 long xPelsPerMeter = iis.readInt();
285 long yPelsPerMeter = iis.readInt();
286 long colorsUsed = iis.readUnsignedInt();
287 long colorsImportant = iis.readUnsignedInt();
288
289 metadata.compression = (int)compression;
290 metadata.xPixelsPerMeter = (int)xPelsPerMeter;
291 metadata.yPixelsPerMeter = (int)yPelsPerMeter;
292 metadata.colorsUsed = (int)colorsUsed;
293 metadata.colorsImportant = (int)colorsImportant;
294
295 if (size == 40) {
296
297 switch((int)compression) {
298
299 case BI_JPEG:
300 case BI_PNG:
301 metadata.bmpVersion = VERSION_3;
302 imageType = VERSION_3_XP_EMBEDDED;
303 break;
304
305 case BI_RGB:
306 case BI_RLE8:
307 case BI_RLE4:
308
309
310 int numberOfEntries = (int)((bitmapOffset-14-size) / 4);
311 int sizeOfPalette = numberOfEntries * 4;
312 palette = new byte[sizeOfPalette];
313 iis.readFully(palette, 0, sizeOfPalette);
314
315 metadata.palette = palette;
316 metadata.paletteSize = numberOfEntries;
317
318 if (bitsPerPixel == 1) {
319 imageType = VERSION_3_1_BIT;
320 } else if (bitsPerPixel == 4) {
321 imageType = VERSION_3_4_BIT;
322 } else if (bitsPerPixel == 8) {
323 imageType = VERSION_3_8_BIT;
324 } else if (bitsPerPixel == 24) {
325 imageType = VERSION_3_24_BIT;
326 } else if (bitsPerPixel == 16) {
327 imageType = VERSION_3_NT_16_BIT;
328
329 redMask = 0x7C00;
330 greenMask = 0x3E0;
331 blueMask = (1 << 5) - 1;
332 metadata.redMask = redMask;
333 metadata.greenMask = greenMask;
334 metadata.blueMask = blueMask;
335 } else if (bitsPerPixel == 32) {
336 imageType = VERSION_3_NT_32_BIT;
337 redMask = 0x00FF0000;
338 greenMask = 0x0000FF00;
339 blueMask = 0x000000FF;
340 metadata.redMask = redMask;
341 metadata.greenMask = greenMask;
342 metadata.blueMask = blueMask;
343 }
344
345 metadata.bmpVersion = VERSION_3;
346 break;
347
348 case BI_BITFIELDS:
349
350 if (bitsPerPixel == 16) {
351 imageType = VERSION_3_NT_16_BIT;
352 } else if (bitsPerPixel == 32) {
353 imageType = VERSION_3_NT_32_BIT;
354 }
355
356
357 redMask = (int)iis.readUnsignedInt();
358 greenMask = (int)iis.readUnsignedInt();
359 blueMask = (int)iis.readUnsignedInt();
360 metadata.redMask = redMask;
361 metadata.greenMask = greenMask;
362 metadata.blueMask = blueMask;
363
364 if (colorsUsed != 0) {
365
366 sizeOfPalette = (int)colorsUsed*4;
367 palette = new byte[sizeOfPalette];
368 iis.readFully(palette, 0, sizeOfPalette);
369
370 metadata.palette = palette;
371 metadata.paletteSize = (int)colorsUsed;
372 }
373 metadata.bmpVersion = VERSION_3_NT;
374
375 break;
376 default:
377 throw new
378 RuntimeException(I18N.getString("BMPImageReader2"));
379 }
380 } else if (size == 108 || size == 124) {
381
382 if (size == 108)
383 metadata.bmpVersion = VERSION_4;
384 else if (size == 124)
385 metadata.bmpVersion = VERSION_5;
386
387
388 redMask = (int)iis.readUnsignedInt();
389 greenMask = (int)iis.readUnsignedInt();
390 blueMask = (int)iis.readUnsignedInt();
391
392 alphaMask = (int)iis.readUnsignedInt();
393 long csType = iis.readUnsignedInt();
394 int redX = iis.readInt();
395 int redY = iis.readInt();
396 int redZ = iis.readInt();
397 int greenX = iis.readInt();
398 int greenY = iis.readInt();
399 int greenZ = iis.readInt();
400 int blueX = iis.readInt();
401 int blueY = iis.readInt();
402 int blueZ = iis.readInt();
403 long gammaRed = iis.readUnsignedInt();
404 long gammaGreen = iis.readUnsignedInt();
405 long gammaBlue = iis.readUnsignedInt();
406
407 if (size == 124) {
408 metadata.intent = iis.readInt();
409 profileData = iis.readInt();
410 profileSize = iis.readInt();
411 iis.skipBytes(4);
412 }
413
414 metadata.colorSpace = (int)csType;
415
416 if (csType == LCS_CALIBRATED_RGB) {
417
418 metadata.redX = redX;
419 metadata.redY = redY;
420 metadata.redZ = redZ;
421 metadata.greenX = greenX;
422 metadata.greenY = greenY;
423 metadata.greenZ = greenZ;
424 metadata.blueX = blueX;
425 metadata.blueY = blueY;
426 metadata.blueZ = blueZ;
427 metadata.gammaRed = (int)gammaRed;
428 metadata.gammaGreen = (int)gammaGreen;
429 metadata.gammaBlue = (int)gammaBlue;
430 }
431
432
433 int numberOfEntries = (int)((bitmapOffset-14-size) / 4);
434 int sizeOfPalette = numberOfEntries*4;
435 palette = new byte[sizeOfPalette];
436 iis.readFully(palette, 0, sizeOfPalette);
437 metadata.palette = palette;
438 metadata.paletteSize = numberOfEntries;
439
440 switch ((int)compression) {
441 case BI_JPEG:
442 case BI_PNG:
443 if (size == 108) {
444 imageType = VERSION_4_XP_EMBEDDED;
445 } else if (size == 124) {
446 imageType = VERSION_5_XP_EMBEDDED;
447 }
448 break;
449 default:
450 if (bitsPerPixel == 1) {
451 imageType = VERSION_4_1_BIT;
452 } else if (bitsPerPixel == 4) {
453 imageType = VERSION_4_4_BIT;
454 } else if (bitsPerPixel == 8) {
455 imageType = VERSION_4_8_BIT;
456 } else if (bitsPerPixel == 16) {
457 imageType = VERSION_4_16_BIT;
458 if ((int)compression == BI_RGB) {
459 redMask = 0x7C00;
460 greenMask = 0x3E0;
461 blueMask = 0x1F;
462 }
463 } else if (bitsPerPixel == 24) {
464 imageType = VERSION_4_24_BIT;
465 } else if (bitsPerPixel == 32) {
466 imageType = VERSION_4_32_BIT;
467 if ((int)compression == BI_RGB) {
468 redMask = 0x00FF0000;
469 greenMask = 0x0000FF00;
470 blueMask = 0x000000FF;
471 }
472 }
473
474 metadata.redMask = redMask;
475 metadata.greenMask = greenMask;
476 metadata.blueMask = blueMask;
477 metadata.alphaMask = alphaMask;
478 }
479 } else {
480 throw new
481 RuntimeException(I18N.getString("BMPImageReader3"));
482 }
483 }
484
485 if (height > 0) {
486
487 isBottomUp = true;
488 } else {
489
490 isBottomUp = false;
491 height = Math.abs(height);
492 }
493
494
495
496 ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB);
497 if (metadata.colorSpace == PROFILE_LINKED ||
498 metadata.colorSpace == PROFILE_EMBEDDED) {
499
500 iis.mark();
501 iis.skipBytes(profileData - size);
502 byte[] profile = new byte[profileSize];
503 iis.readFully(profile, 0, profileSize);
504 iis.reset();
505
506 try {
507 if (metadata.colorSpace == PROFILE_LINKED &&
508 isLinkedProfileAllowed() &&
509 !isUncOrDevicePath(profile))
510 {
511 String path = new String(profile, "windows-1252");
512
513 colorSpace =
514 new ICC_ColorSpace(ICC_Profile.getInstance(path));
515 } else {
516 colorSpace =
517 new ICC_ColorSpace(ICC_Profile.getInstance(profile));
518 }
519 } catch (Exception e) {
520 colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB);
521 }
522 }
523
524 if (bitsPerPixel == 0 ||
525 compression == BI_JPEG || compression == BI_PNG )
526 {
527
528
529 colorModel = null;
530 sampleModel = null;
531 } else if (bitsPerPixel == 1 || bitsPerPixel == 4 || bitsPerPixel == 8) {
532
533 numBands = 1;
534
535 if (bitsPerPixel == 8) {
536 int[] bandOffsets = new int[numBands];
537 for (int i = 0; i < numBands; i++) {
538 bandOffsets[i] = numBands -1 -i;
539 }
540 sampleModel =
541 new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE,
542 width, height,
543 numBands,
544 numBands * width,
545 bandOffsets);
546 } else {
547
548 sampleModel =
549 new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE,
550 width, height,
551 bitsPerPixel);
552 }
553
554
555 byte r[], g[], b[];
556 if (imageType == VERSION_2_1_BIT ||
557 imageType == VERSION_2_4_BIT ||
558 imageType == VERSION_2_8_BIT) {
559
560
561 size = palette.length/3;
562
563 if (size > 256) {
564 size = 256;
565 }
566
567 int off;
568 r = new byte[(int)size];
569 g = new byte[(int)size];
570 b = new byte[(int)size];
571 for (int i=0; i<(int)size; i++) {
572 off = 3 * i;
573 b[i] = palette[off];
574 g[i] = palette[off+1];
575 r[i] = palette[off+2];
576 }
577 } else {
578 size = palette.length/4;
579
580 if (size > 256) {
581 size = 256;
582 }
583
584 int off;
585 r = new byte[(int)size];
586 g = new byte[(int)size];
587 b = new byte[(int)size];
588 for (int i=0; i<size; i++) {
589 off = 4 * i;
590 b[i] = palette[off];
591 g[i] = palette[off+1];
592 r[i] = palette[off+2];
593 }
594 }
595
596 if (ImageUtil.isIndicesForGrayscale(r, g, b))
597 colorModel =
598 ImageUtil.createColorModel(null, sampleModel);
599 else
600 colorModel = new IndexColorModel(bitsPerPixel, (int)size, r, g, b);
601 } else if (bitsPerPixel == 16) {
602 numBands = 3;
603 sampleModel =
604 new SinglePixelPackedSampleModel(DataBuffer.TYPE_USHORT,
605 width, height,
606 new int[] {redMask, greenMask, blueMask});
607
608 colorModel =
609 new DirectColorModel(colorSpace,
610 16, redMask, greenMask, blueMask, 0,
611 false, DataBuffer.TYPE_USHORT);
612
613 } else if (bitsPerPixel == 32) {
614 numBands = alphaMask == 0 ? 3 : 4;
615
616
617
618 int[] bitMasks = numBands == 3 ?
619 new int[] {redMask, greenMask, blueMask} :
620 new int[] {redMask, greenMask, blueMask, alphaMask};
621
622 sampleModel =
623 new SinglePixelPackedSampleModel(DataBuffer.TYPE_INT,
624 width, height,
625 bitMasks);
626
627 colorModel =
628 new DirectColorModel(colorSpace,
629 32, redMask, greenMask, blueMask, alphaMask,
630 false, DataBuffer.TYPE_INT);
631 } else {
632 numBands = 3;
633
634 int[] bandOffsets = new int[numBands];
635 for (int i = 0; i < numBands; i++) {
636 bandOffsets[i] = numBands -1 -i;
637 }
638
639 sampleModel =
640 new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE,
641 width, height,
642 numBands,
643 numBands * width,
644 bandOffsets);
645
646 colorModel =
647 ImageUtil.createColorModel(colorSpace, sampleModel);
648 }
649
650 originalSampleModel = sampleModel;
651 originalColorModel = colorModel;
652
653
654
655 iis.reset();
656 iis.skipBytes(bitmapOffset);
657 gotHeader = true;
658 }
659
660 public Iterator getImageTypes(int imageIndex)
661 throws IOException {
662 checkIndex(imageIndex);
663 readHeader();
664 ArrayList list = new ArrayList(1);
665 list.add(new ImageTypeSpecifier(originalColorModel,
666 originalSampleModel));
667 return list.iterator();
668 }
669
670 public ImageReadParam getDefaultReadParam() {
671 return new ImageReadParam();
672 }
673
674 public IIOMetadata getImageMetadata(int imageIndex)
675 throws IOException {
676 checkIndex(imageIndex);
677 if (metadata == null) {
678 readHeader();
679 }
680 return metadata;
681 }
682
683 public IIOMetadata getStreamMetadata() throws IOException {
684 return null;
685 }
686
687 public boolean isRandomAccessEasy(int imageIndex) throws IOException {
688 checkIndex(imageIndex);
689 readHeader();
690 return metadata.compression == BI_RGB;
691 }
692
693 public BufferedImage read(int imageIndex, ImageReadParam param)
694 throws IOException {
695
696 if (iis == null) {
697 throw new IllegalStateException(I18N.getString("BMPImageReader5"));
698 }
699
700 checkIndex(imageIndex);
701 clearAbortRequest();
702 processImageStarted(imageIndex);
703
704 if (param == null)
705 param = getDefaultReadParam();
706
707
708 readHeader();
709
710 sourceRegion = new Rectangle(0, 0, 0, 0);
711 destinationRegion = new Rectangle(0, 0, 0, 0);
712
713 computeRegions(param, this.width, this.height,
714 param.getDestination(),
715 sourceRegion,
716 destinationRegion);
717
718 scaleX = param.getSourceXSubsampling();
719 scaleY = param.getSourceYSubsampling();
720
721
722 sourceBands = param.getSourceBands();
723 destBands = param.getDestinationBands();
724
725 seleBand = (sourceBands != null) && (destBands != null);
726 noTransform =
727 destinationRegion.equals(new Rectangle(0, 0, width, height)) ||
728 seleBand;
729
730 if (!seleBand) {
731 sourceBands = new int[numBands];
732 destBands = new int[numBands];
733 for (int i = 0; i < numBands; i++)
734 destBands[i] = sourceBands[i] = i;
735 }
736
737
738 bi = param.getDestination();
739
740
741 WritableRaster raster = null;
742
743 if (bi == null) {
744 if (sampleModel != null && colorModel != null) {
745 sampleModel =
746 sampleModel.createCompatibleSampleModel(destinationRegion.x +
747 destinationRegion.width,
748 destinationRegion.y +
749 destinationRegion.height);
750 if (seleBand)
751 sampleModel = sampleModel.createSubsetSampleModel(sourceBands);
752 raster = Raster.createWritableRaster(sampleModel, new Point());
753 bi = new BufferedImage(colorModel, raster, false, null);
754 }
755 } else {
756 raster = bi.getWritableTile(0, 0);
757 sampleModel = bi.getSampleModel();
758 colorModel = bi.getColorModel();
759
760 noTransform &= destinationRegion.equals(raster.getBounds());
761 }
762
763 byte bdata[] = null;
764 short sdata[] = null;
765 int idata[] = null;
766
767
768 if (sampleModel != null) {
769 if (sampleModel.getDataType() == DataBuffer.TYPE_BYTE)
770 bdata = (byte[])
771 ((DataBufferByte)raster.getDataBuffer()).getData();
772 else if (sampleModel.getDataType() == DataBuffer.TYPE_USHORT)
773 sdata = (short[])
774 ((DataBufferUShort)raster.getDataBuffer()).getData();
775 else if (sampleModel.getDataType() == DataBuffer.TYPE_INT)
776 idata = (int[])
777 ((DataBufferInt)raster.getDataBuffer()).getData();
778 }
779
780
781 switch(imageType) {
782
783 case VERSION_2_1_BIT:
784
785 read1Bit(bdata);
786 break;
787
788 case VERSION_2_4_BIT:
789
790 read4Bit(bdata);
791 break;
792
793 case VERSION_2_8_BIT:
794
795 read8Bit(bdata);
796 break;
797
798 case VERSION_2_24_BIT:
799
800 read24Bit(bdata);
801 break;
802
803 case VERSION_3_1_BIT:
804
805 read1Bit(bdata);
806 break;
807
808 case VERSION_3_4_BIT:
809 switch((int)compression) {
810 case BI_RGB:
811 read4Bit(bdata);
812 break;
813
814 case BI_RLE4:
815 readRLE4(bdata);
816 break;
817
818 default:
819 throw new
820 RuntimeException(I18N.getString("BMPImageReader1"));
821 }
822 break;
823
824 case VERSION_3_8_BIT:
825 switch((int)compression) {
826 case BI_RGB:
827 read8Bit(bdata);
828 break;
829
830 case BI_RLE8:
831 readRLE8(bdata);
832 break;
833
834 default:
835 throw new
836 RuntimeException(I18N.getString("BMPImageReader1"));
837 }
838
839 break;
840
841 case VERSION_3_24_BIT:
842
843 read24Bit(bdata);
844 break;
845
846 case VERSION_3_NT_16_BIT:
847 read16Bit(sdata);
848 break;
849
850 case VERSION_3_NT_32_BIT:
851 read32Bit(idata);
852 break;
853
854 case VERSION_3_XP_EMBEDDED:
855 case VERSION_4_XP_EMBEDDED:
856 case VERSION_5_XP_EMBEDDED:
857 bi = readEmbedded((int)compression, bi, param);
858 break;
859
860 case VERSION_4_1_BIT:
861 read1Bit(bdata);
862 break;
863
864 case VERSION_4_4_BIT:
865 switch((int)compression) {
866
867 case BI_RGB:
868 read4Bit(bdata);
869 break;
870
871 case BI_RLE4:
872 readRLE4(bdata);
873 break;
874
875 default:
876 throw new
877 RuntimeException(I18N.getString("BMPImageReader1"));
878 }
879
880 case VERSION_4_8_BIT:
881 switch((int)compression) {
882
883 case BI_RGB:
884 read8Bit(bdata);
885 break;
886
887 case BI_RLE8:
888 readRLE8(bdata);
889 break;
890
891 default:
892 throw new
893 RuntimeException(I18N.getString("BMPImageReader1"));
894 }
895 break;
896
897 case VERSION_4_16_BIT:
898 read16Bit(sdata);
899 break;
900
901 case VERSION_4_24_BIT:
902 read24Bit(bdata);
903 break;
904
905 case VERSION_4_32_BIT:
906 read32Bit(idata);
907 break;
908 }
909
910 if (abortRequested())
911 processReadAborted();
912 else
913 processImageComplete();
914
915 return bi;
916 }
917
918 public boolean canReadRaster() {
919 return true;
920 }
921
922 public Raster readRaster(int imageIndex,
923 ImageReadParam param) throws IOException {
924 BufferedImage bi = read(imageIndex, param);
925 return bi.getData();
926 }
927
928 private void resetHeaderInfo() {
929 gotHeader = false;
930 bi = null;
931 sampleModel = originalSampleModel = null;
932 colorModel = originalColorModel = null;
933 }
934
935 public void reset() {
936 super.reset();
937 iis = null;
938 resetHeaderInfo();
939 }
940
941
942 private void read1Bit(byte[] bdata) throws IOException {
943 int bytesPerScanline = (width + 7) / 8;
944 int padding = bytesPerScanline % 4;
945 if (padding != 0) {
946 padding = 4 - padding;
947 }
948
949 int lineLength = bytesPerScanline + padding;
950
951 if (noTransform) {
952 int j = isBottomUp ? (height -1)*bytesPerScanline : 0;
953
954 for (int i=0; i<height; i++) {
955 if (abortRequested()) {
956 break;
957 }
958 iis.readFully(bdata, j, bytesPerScanline);
959 iis.skipBytes(padding);
960 j += isBottomUp ? -bytesPerScanline : bytesPerScanline;
961 processImageUpdate(bi, 0, i,
962 destinationRegion.width, 1, 1, 1,
963 new int[]{0});
964 processImageProgress(100.0F * i/destinationRegion.height);
965 }
966 } else {
967 byte[] buf = new byte[lineLength];
968 int lineStride =
969 ((MultiPixelPackedSampleModel)sampleModel).getScanlineStride();
970
971 if (isBottomUp) {
972 int lastLine =
973 sourceRegion.y + (destinationRegion.height - 1) * scaleY;
974 iis.skipBytes(lineLength * (height - 1 - lastLine));
975 } else
976 iis.skipBytes(lineLength * sourceRegion.y);
977
978 int skipLength = lineLength * (scaleY - 1);
979
980
981 int[] srcOff = new int[destinationRegion.width];
982 int[] destOff = new int[destinationRegion.width];
983 int[] srcPos = new int[destinationRegion.width];
984 int[] destPos = new int[destinationRegion.width];
985
986 for (int i = destinationRegion.x, x = sourceRegion.x, j = 0;
987 i < destinationRegion.x + destinationRegion.width;
988 i++, j++, x += scaleX) {
989 srcPos[j] = x >> 3;
990 srcOff[j] = 7 - (x & 7);
991 destPos[j] = i >> 3;
992 destOff[j] = 7 - (i & 7);
993 }
994
995 int k = destinationRegion.y * lineStride;
996 if (isBottomUp)
997 k += (destinationRegion.height - 1) * lineStride;
998
999 for (int j = 0, y = sourceRegion.y;
1000 j < destinationRegion.height; j++, y+=scaleY) {
1001
1002 if (abortRequested())
1003 break;
1004 iis.read(buf, 0, lineLength);
1005 for (int i = 0; i < destinationRegion.width; i++) {
1006
1007 int v = (buf[srcPos[i]] >> srcOff[i]) & 1;
1008 bdata[k + destPos[i]] |= v << destOff[i];
1009 }
1010
1011 k += isBottomUp ? -lineStride : lineStride;
1012 iis.skipBytes(skipLength);
1013 processImageUpdate(bi, 0, j,
1014 destinationRegion.width, 1, 1, 1,
1015 new int[]{0});
1016 processImageProgress(100.0F*j/destinationRegion.height);
1017 }
1018 }
1019 }
1020
1021
1022 private void read4Bit(byte[] bdata) throws IOException {
1023
1024 int bytesPerScanline = (width + 1) / 2;
1025
1026
1027 int padding = bytesPerScanline % 4;
1028 if (padding != 0)
1029 padding = 4 - padding;
1030
1031 int lineLength = bytesPerScanline + padding;
1032
1033 if (noTransform) {
1034 int j = isBottomUp ? (height -1) * bytesPerScanline : 0;
1035
1036 for (int i=0; i<height; i++) {
1037 if (abortRequested()) {
1038 break;
1039 }
1040 iis.readFully(bdata, j, bytesPerScanline);
1041 iis.skipBytes(padding);
1042 j += isBottomUp ? -bytesPerScanline : bytesPerScanline;
1043 processImageUpdate(bi, 0, i,
1044 destinationRegion.width, 1, 1, 1,
1045 new int[]{0});
1046 processImageProgress(100.0F * i/destinationRegion.height);
1047 }
1048 } else {
1049 byte[] buf = new byte[lineLength];
1050 int lineStride =
1051 ((MultiPixelPackedSampleModel)sampleModel).getScanlineStride();
1052
1053 if (isBottomUp) {
1054 int lastLine =
1055 sourceRegion.y + (destinationRegion.height - 1) * scaleY;
1056 iis.skipBytes(lineLength * (height - 1 - lastLine));
1057 } else
1058 iis.skipBytes(lineLength * sourceRegion.y);
1059
1060 int skipLength = lineLength * (scaleY - 1);
1061
1062
1063 int[] srcOff = new int[destinationRegion.width];
1064 int[] destOff = new int[destinationRegion.width];
1065 int[] srcPos = new int[destinationRegion.width];
1066 int[] destPos = new int[destinationRegion.width];
1067
1068 for (int i = destinationRegion.x, x = sourceRegion.x, j = 0;
1069 i < destinationRegion.x + destinationRegion.width;
1070 i++, j++, x += scaleX) {
1071 srcPos[j] = x >> 1;
1072 srcOff[j] = (1 - (x & 1)) << 2;
1073 destPos[j] = i >> 1;
1074 destOff[j] = (1 - (i & 1)) << 2;
1075 }
1076
1077 int k = destinationRegion.y * lineStride;
1078 if (isBottomUp)
1079 k += (destinationRegion.height - 1) * lineStride;
1080
1081 for (int j = 0, y = sourceRegion.y;
1082 j < destinationRegion.height; j++, y+=scaleY) {
1083
1084 if (abortRequested())
1085 break;
1086 iis.read(buf, 0, lineLength);
1087 for (int i = 0; i < destinationRegion.width; i++) {
1088
1089 int v = (buf[srcPos[i]] >> srcOff[i]) & 0x0F;
1090 bdata[k + destPos[i]] |= v << destOff[i];
1091 }
1092
1093 k += isBottomUp ? -lineStride : lineStride;
1094 iis.skipBytes(skipLength);
1095 processImageUpdate(bi, 0, j,
1096 destinationRegion.width, 1, 1, 1,
1097 new int[]{0});
1098 processImageProgress(100.0F*j/destinationRegion.height);
1099 }
1100 }
1101 }
1102
1103
1104 private void read8Bit(byte[] bdata) throws IOException {
1105
1106
1107 int padding = width % 4;
1108 if (padding != 0) {
1109 padding = 4 - padding;
1110 }
1111
1112 int lineLength = width + padding;
1113
1114 if (noTransform) {
1115 int j = isBottomUp ? (height -1) * width : 0;
1116
1117 for (int i=0; i<height; i++) {
1118 if (abortRequested()) {
1119 break;
1120 }
1121 iis.readFully(bdata, j, width);
1122 iis.skipBytes(padding);
1123 j += isBottomUp ? -width : width;
1124 processImageUpdate(bi, 0, i,
1125 destinationRegion.width, 1, 1, 1,
1126 new int[]{0});
1127 processImageProgress(100.0F * i/destinationRegion.height);
1128 }
1129 } else {
1130 byte[] buf = new byte[lineLength];
1131 int lineStride =
1132 ((ComponentSampleModel)sampleModel).getScanlineStride();
1133
1134 if (isBottomUp) {
1135 int lastLine =
1136 sourceRegion.y + (destinationRegion.height - 1) * scaleY;
1137 iis.skipBytes(lineLength * (height - 1 - lastLine));
1138 } else
1139 iis.skipBytes(lineLength * sourceRegion.y);
1140
1141 int skipLength = lineLength * (scaleY - 1);
1142
1143 int k = destinationRegion.y * lineStride;
1144 if (isBottomUp)
1145 k += (destinationRegion.height - 1) * lineStride;
1146 k += destinationRegion.x;
1147
1148 for (int j = 0, y = sourceRegion.y;
1149 j < destinationRegion.height; j++, y+=scaleY) {
1150
1151 if (abortRequested())
1152 break;
1153 iis.read(buf, 0, lineLength);
1154 for (int i = 0, m = sourceRegion.x;
1155 i < destinationRegion.width; i++, m += scaleX) {
1156
1157 bdata[k + i] = buf[m];
1158 }
1159
1160 k += isBottomUp ? -lineStride : lineStride;
1161 iis.skipBytes(skipLength);
1162 processImageUpdate(bi, 0, j,
1163 destinationRegion.width, 1, 1, 1,
1164 new int[]{0});
1165 processImageProgress(100.0F*j/destinationRegion.height);
1166 }
1167 }
1168 }
1169
1170
1171 private void read24Bit(byte[] bdata) throws IOException {
1172
1173
1174 int padding = width * 3 % 4;
1175 if ( padding != 0)
1176 padding = 4 - padding;
1177
1178 int lineStride = width * 3;
1179 int lineLength = lineStride + padding;
1180
1181 if (noTransform) {
1182 int j = isBottomUp ? (height -1) * width * 3 : 0;
1183
1184 for (int i=0; i<height; i++) {
1185 if (abortRequested()) {
1186 break;
1187 }
1188 iis.readFully(bdata, j, lineStride);
1189 iis.skipBytes(padding);
1190 j += isBottomUp ? -lineStride : lineStride;
1191 processImageUpdate(bi, 0, i,
1192 destinationRegion.width, 1, 1, 1,
1193 new int[]{0});
1194 processImageProgress(100.0F * i/destinationRegion.height);
1195 }
1196 } else {
1197 byte[] buf = new byte[lineLength];
1198 lineStride =
1199 ((ComponentSampleModel)sampleModel).getScanlineStride();
1200
1201 if (isBottomUp) {
1202 int lastLine =
1203 sourceRegion.y + (destinationRegion.height - 1) * scaleY;
1204 iis.skipBytes(lineLength * (height - 1 - lastLine));
1205 } else
1206 iis.skipBytes(lineLength * sourceRegion.y);
1207
1208 int skipLength = lineLength * (scaleY - 1);
1209
1210 int k = destinationRegion.y * lineStride;
1211 if (isBottomUp)
1212 k += (destinationRegion.height - 1) * lineStride;
1213 k += destinationRegion.x * 3;
1214
1215 for (int j = 0, y = sourceRegion.y;
1216 j < destinationRegion.height; j++, y+=scaleY) {
1217
1218 if (abortRequested())
1219 break;
1220 iis.read(buf, 0, lineLength);
1221 for (int i = 0, m = 3 * sourceRegion.x;
1222 i < destinationRegion.width; i++, m += 3 * scaleX) {
1223
1224 int n = 3 * i + k;
1225 for (int b = 0; b < destBands.length; b++)
1226 bdata[n + destBands[b]] = buf[m + sourceBands[b]];
1227 }
1228
1229 k += isBottomUp ? -lineStride : lineStride;
1230 iis.skipBytes(skipLength);
1231 processImageUpdate(bi, 0, j,
1232 destinationRegion.width, 1, 1, 1,
1233 new int[]{0});
1234 processImageProgress(100.0F*j/destinationRegion.height);
1235 }
1236 }
1237 }
1238
1239 private void read16Bit(short sdata[]) throws IOException {
1240
1241
1242 int padding = width * 2 % 4;
1243
1244 if ( padding != 0)
1245 padding = 4 - padding;
1246
1247 int lineLength = width + padding / 2;
1248
1249 if (noTransform) {
1250 int j = isBottomUp ? (height -1) * width : 0;
1251 for (int i=0; i<height; i++) {
1252 if (abortRequested()) {
1253 break;
1254 }
1255
1256 iis.readFully(sdata, j, width);
1257 iis.skipBytes(padding);
1258
1259 j += isBottomUp ? -width : width;
1260 processImageUpdate(bi, 0, i,
1261 destinationRegion.width, 1, 1, 1,
1262 new int[]{0});
1263 processImageProgress(100.0F * i/destinationRegion.height);
1264 }
1265 } else {
1266 short[] buf = new short[lineLength];
1267 int lineStride =
1268 ((SinglePixelPackedSampleModel)sampleModel).getScanlineStride();
1269
1270 if (isBottomUp) {
1271 int lastLine =
1272 sourceRegion.y + (destinationRegion.height - 1) * scaleY;
1273 iis.skipBytes(lineLength * (height - 1 - lastLine) << 1);
1274 } else
1275 iis.skipBytes(lineLength * sourceRegion.y << 1);
1276
1277 int skipLength = lineLength * (scaleY - 1) << 1;
1278
1279 int k = destinationRegion.y * lineStride;
1280 if (isBottomUp)
1281 k += (destinationRegion.height - 1) * lineStride;
1282 k += destinationRegion.x;
1283
1284 for (int j = 0, y = sourceRegion.y;
1285 j < destinationRegion.height; j++, y+=scaleY) {
1286
1287 if (abortRequested())
1288 break;
1289 iis.readFully(buf, 0, lineLength);
1290 for (int i = 0, m = sourceRegion.x;
1291 i < destinationRegion.width; i++, m += scaleX) {
1292
1293 sdata[k + i] = buf[m];
1294 }
1295
1296 k += isBottomUp ? -lineStride : lineStride;
1297 iis.skipBytes(skipLength);
1298 processImageUpdate(bi, 0, j,
1299 destinationRegion.width, 1, 1, 1,
1300 new int[]{0});
1301 processImageProgress(100.0F*j/destinationRegion.height);
1302 }
1303 }
1304 }
1305
1306 private void read32Bit(int idata[]) throws IOException {
1307 if (noTransform) {
1308 int j = isBottomUp ? (height -1) * width : 0;
1309
1310 for (int i=0; i<height; i++) {
1311 if (abortRequested()) {
1312 break;
1313 }
1314 iis.readFully(idata, j, width);
1315 j += isBottomUp ? -width : width;
1316 processImageUpdate(bi, 0, i,
1317 destinationRegion.width, 1, 1, 1,
1318 new int[]{0});
1319 processImageProgress(100.0F * i/destinationRegion.height);
1320 }
1321 } else {
1322 int[] buf = new int[width];
1323 int lineStride =
1324 ((SinglePixelPackedSampleModel)sampleModel).getScanlineStride();
1325
1326 if (isBottomUp) {
1327 int lastLine =
1328 sourceRegion.y + (destinationRegion.height - 1) * scaleY;
1329 iis.skipBytes(width * (height - 1 - lastLine) << 2);
1330 } else
1331 iis.skipBytes(width * sourceRegion.y << 2);
1332
1333 int skipLength = width * (scaleY - 1) << 2;
1334
1335 int k = destinationRegion.y * lineStride;
1336 if (isBottomUp)
1337 k += (destinationRegion.height - 1) * lineStride;
1338 k += destinationRegion.x;
1339
1340 for (int j = 0, y = sourceRegion.y;
1341 j < destinationRegion.height; j++, y+=scaleY) {
1342
1343 if (abortRequested())
1344 break;
1345 iis.readFully(buf, 0, width);
1346 for (int i = 0, m = sourceRegion.x;
1347 i < destinationRegion.width; i++, m += scaleX) {
1348
1349 idata[k + i] = buf[m];
1350 }
1351
1352 k += isBottomUp ? -lineStride : lineStride;
1353 iis.skipBytes(skipLength);
1354 processImageUpdate(bi, 0, j,
1355 destinationRegion.width, 1, 1, 1,
1356 new int[]{0});
1357 processImageProgress(100.0F*j/destinationRegion.height);
1358 }
1359 }
1360 }
1361
1362 private void readRLE8(byte bdata[]) throws IOException {
1363
1364 int imSize = (int)imageSize;
1365 if (imSize == 0) {
1366 imSize = (int)(bitmapFileSize - bitmapOffset);
1367 }
1368
1369 int padding = 0;
1370
1371
1372 int remainder = width % 4;
1373 if (remainder != 0) {
1374 padding = 4 - remainder;
1375 }
1376
1377
1378 byte values[] = new byte[imSize];
1379 int bytesRead = 0;
1380 iis.readFully(values, 0, imSize);
1381
1382
1383 decodeRLE8(imSize, padding, values, bdata);
1384 }
1385
1386 private void decodeRLE8(int imSize,
1387 int padding,
1388 byte[] values,
1389 byte[] bdata) throws IOException {
1390
1391 byte val[] = new byte[width * height];
1392 int count = 0, l = 0;
1393 int value;
1394 boolean flag = false;
1395 int lineNo = isBottomUp ? height - 1 : 0;
1396 int lineStride =
1397 ((ComponentSampleModel)sampleModel).getScanlineStride();
1398 int finished = 0;
1399
1400 while (count != imSize) {
1401 value = values[count++] & 0xff;
1402 if (value == 0) {
1403 switch(values[count++] & 0xff) {
1404
1405 case 0:
1406
1407 if (lineNo >= sourceRegion.y &&
1408 lineNo < sourceRegion.y + sourceRegion.height) {
1409 if (noTransform) {
1410 int pos = lineNo * width;
1411 for(int i = 0; i < width; i++)
1412 bdata[pos++] = val[i];
1413 processImageUpdate(bi, 0, lineNo,
1414 destinationRegion.width, 1, 1, 1,
1415 new int[]{0});
1416 finished++;
1417 } else if ((lineNo - sourceRegion.y) % scaleY == 0) {
1418 int currentLine = (lineNo - sourceRegion.y) / scaleY +
1419 destinationRegion.y;
1420 int pos = currentLine * lineStride;
1421 pos += destinationRegion.x;
1422 for (int i = sourceRegion.x;
1423 i < sourceRegion.x + sourceRegion.width;
1424 i += scaleX)
1425 bdata[pos++] = val[i];
1426 processImageUpdate(bi, 0, currentLine,
1427 destinationRegion.width, 1, 1, 1,
1428 new int[]{0});
1429 finished++;
1430 }
1431 }
1432 processImageProgress(100.0F * finished / destinationRegion.height);
1433 lineNo += isBottomUp ? -1 : 1;
1434 l = 0;
1435
1436 if (abortRequested()) {
1437 flag = true;
1438 }
1439
1440 break;
1441
1442 case 1:
1443
1444 flag = true;
1445 break;
1446
1447 case 2:
1448
1449 int xoff = values[count++] & 0xff;
1450 int yoff = values[count] & 0xff;
1451
1452 l += xoff + yoff*width;
1453 break;
1454
1455 default:
1456 int end = values[count-1] & 0xff;
1457 for (int i=0; i<end; i++) {
1458 val[l++] = (byte)(values[count++] & 0xff);
1459 }
1460
1461
1462
1463 if ((end & 1) == 1) {
1464 count++;
1465 }
1466 }
1467 } else {
1468 for (int i=0; i<value; i++) {
1469 val[l++] = (byte)(values[count] & 0xff);
1470 }
1471
1472 count++;
1473 }
1474
1475
1476 if (flag) {
1477 break;
1478 }
1479 }
1480 }
1481
1482 private void readRLE4(byte[] bdata) throws IOException {
1483
1484
1485 int imSize = (int)imageSize;
1486 if (imSize == 0) {
1487 imSize = (int)(bitmapFileSize - bitmapOffset);
1488 }
1489
1490 int padding = 0;
1491
1492
1493 int remainder = width % 4;
1494 if (remainder != 0) {
1495 padding = 4 - remainder;
1496 }
1497
1498
1499 byte[] values = new byte[imSize];
1500 iis.readFully(values, 0, imSize);
1501
1502
1503 decodeRLE4(imSize, padding, values, bdata);
1504 }
1505
1506 private void decodeRLE4(int imSize,
1507 int padding,
1508 byte[] values,
1509 byte[] bdata) throws IOException {
1510 byte[] val = new byte[width];
1511 int count = 0, l = 0;
1512 int value;
1513 boolean flag = false;
1514 int lineNo = isBottomUp ? height - 1 : 0;
1515 int lineStride =
1516 ((MultiPixelPackedSampleModel)sampleModel).getScanlineStride();
1517 int finished = 0;
1518
1519 while (count != imSize) {
1520
1521 value = values[count++] & 0xFF;
1522 if (value == 0) {
1523
1524
1525
1526 switch(values[count++] & 0xFF) {
1527
1528 case 0:
1529
1530
1531 if (lineNo >= sourceRegion.y &&
1532 lineNo < sourceRegion.y + sourceRegion.height) {
1533 if (noTransform) {
1534 int pos = lineNo * (width + 1 >> 1);
1535 for(int i = 0, j = 0; i < width >> 1; i++)
1536 bdata[pos++] =
1537 (byte)((val[j++] << 4) | val[j++]);
1538 if ((width & 1) == 1)
1539 bdata[pos] |= val[width - 1] << 4;
1540
1541 processImageUpdate(bi, 0, lineNo,
1542 destinationRegion.width, 1, 1, 1,
1543 new int[]{0});
1544 finished++;
1545 } else if ((lineNo - sourceRegion.y) % scaleY == 0) {
1546 int currentLine = (lineNo - sourceRegion.y) / scaleY +
1547 destinationRegion.y;
1548 int pos = currentLine * lineStride;
1549 pos += destinationRegion.x >> 1;
1550 int shift = (1 - (destinationRegion.x & 1)) << 2;
1551 for (int i = sourceRegion.x;
1552 i < sourceRegion.x + sourceRegion.width;
1553 i += scaleX) {
1554 bdata[pos] |= val[i] << shift;
1555 shift += 4;
1556 if (shift == 4) {
1557 pos++;
1558 }
1559 shift &= 7;
1560 }
1561 processImageUpdate(bi, 0, currentLine,
1562 destinationRegion.width, 1, 1, 1,
1563 new int[]{0});
1564 finished++;
1565 }
1566 }
1567 processImageProgress(100.0F * finished / destinationRegion.height);
1568 lineNo += isBottomUp ? -1 : 1;
1569 l = 0;
1570
1571 if (abortRequested()) {
1572 flag = true;
1573 }
1574
1575 break;
1576
1577 case 1:
1578
1579 flag = true;
1580 break;
1581
1582 case 2:
1583
1584 int xoff = values[count++] & 0xFF;
1585 int yoff = values[count] & 0xFF;
1586
1587 l += xoff + yoff*width;
1588 break;
1589
1590 default:
1591 int end = values[count-1] & 0xFF;
1592 for (int i=0; i<end; i++) {
1593 val[l++] = (byte)(((i & 1) == 0) ? (values[count] & 0xf0) >> 4
1594 : (values[count++] & 0x0f));
1595 }
1596
1597
1598
1599 if ((end & 1) == 1) {
1600 count++;
1601 }
1602
1603
1604
1605 if ((((int)Math.ceil(end/2)) & 1) ==1 ) {
1606 count++;
1607 }
1608 break;
1609 }
1610 } else {
1611
1612 int alternate[] = { (values[count] & 0xf0) >> 4,
1613 values[count] & 0x0f };
1614 for (int i=0; (i < value) && (l < width); i++) {
1615 val[l++] = (byte)alternate[i & 1];
1616 }
1617
1618 count++;
1619 }
1620
1621
1622 if (flag) {
1623 break;
1624 }
1625 }
1626 }
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637 private BufferedImage readEmbedded(int type,
1638 BufferedImage bi, ImageReadParam bmpParam)
1639 throws IOException {
1640 String format;
1641 switch(type) {
1642 case BI_JPEG:
1643 format = "JPEG";
1644 break;
1645 case BI_PNG:
1646 format = "PNG";
1647 break;
1648 default:
1649 throw new
1650 IOException("Unexpected compression type: " + type);
1651 }
1652 ImageReader reader =
1653 ImageIO.getImageReadersByFormatName(format).next();
1654 if (reader == null) {
1655 throw new RuntimeException(I18N.getString("BMPImageReader4") +
1656 " " + format);
1657 }
1658
1659 byte[] buff = new byte[(int)imageSize];
1660 iis.read(buff);
1661 reader.setInput(ImageIO.createImageInputStream(new ByteArrayInputStream(buff)));
1662 if (bi == null) {
1663 ImageTypeSpecifier embType = reader.getImageTypes(0).next();
1664 bi = embType.createBufferedImage(destinationRegion.x +
1665 destinationRegion.width,
1666 destinationRegion.y +
1667 destinationRegion.height);
1668 }
1669
1670 reader.addIIOReadProgressListener(new EmbeddedProgressAdapter() {
1671 public void imageProgress(ImageReader source,
1672 float percentageDone)
1673 {
1674 processImageProgress(percentageDone);
1675 }
1676 });
1677
1678 reader.addIIOReadUpdateListener(new IIOReadUpdateListener() {
1679 public void imageUpdate(ImageReader source,
1680 BufferedImage theImage,
1681 int minX, int minY,
1682 int width, int height,
1683 int periodX, int periodY,
1684 int[] bands)
1685 {
1686 processImageUpdate(theImage, minX, minY,
1687 width, height,
1688 periodX, periodY, bands);
1689 }
1690 public void passComplete(ImageReader source,
1691 BufferedImage theImage)
1692 {
1693 processPassComplete(theImage);
1694 }
1695 public void passStarted(ImageReader source,
1696 BufferedImage theImage,
1697 int pass,
1698 int minPass, int maxPass,
1699 int minX, int minY,
1700 int periodX, int periodY,
1701 int[] bands)
1702 {
1703 processPassStarted(theImage, pass, minPass, maxPass,
1704 minX, minY, periodX, periodY,
1705 bands);
1706 }
1707 public void thumbnailPassComplete(ImageReader source,
1708 BufferedImage thumb) {}
1709 public void thumbnailPassStarted(ImageReader source,
1710 BufferedImage thumb,
1711 int pass,
1712 int minPass, int maxPass,
1713 int minX, int minY,
1714 int periodX, int periodY,
1715 int[] bands) {}
1716 public void thumbnailUpdate(ImageReader source,
1717 BufferedImage theThumbnail,
1718 int minX, int minY,
1719 int width, int height,
1720 int periodX, int periodY,
1721 int[] bands) {}
1722 });
1723
1724 reader.addIIOReadWarningListener(new IIOReadWarningListener() {
1725 public void warningOccurred(ImageReader source, String warning)
1726 {
1727 processWarningOccurred(warning);
1728 }
1729 });
1730
1731 ImageReadParam param = reader.getDefaultReadParam();
1732 param.setDestination(bi);
1733 param.setDestinationBands(bmpParam.getDestinationBands());
1734 param.setDestinationOffset(bmpParam.getDestinationOffset());
1735 param.setSourceBands(bmpParam.getSourceBands());
1736 param.setSourceRegion(bmpParam.getSourceRegion());
1737 param.setSourceSubsampling(bmpParam.getSourceXSubsampling(),
1738 bmpParam.getSourceYSubsampling(),
1739 bmpParam.getSubsamplingXOffset(),
1740 bmpParam.getSubsamplingYOffset());
1741 reader.read(0, param);
1742 return bi;
1743 }
1744
1745 private class EmbeddedProgressAdapter implements IIOReadProgressListener {
1746 public void imageComplete(ImageReader src) {}
1747 public void imageProgress(ImageReader src, float percentageDone) {}
1748 public void imageStarted(ImageReader src, int imageIndex) {}
1749 public void thumbnailComplete(ImageReader src) {}
1750 public void thumbnailProgress(ImageReader src, float percentageDone) {}
1751 public void thumbnailStarted(ImageReader src, int iIdx, int tIdx) {}
1752 public void sequenceComplete(ImageReader src) {}
1753 public void sequenceStarted(ImageReader src, int minIndex) {}
1754 public void readAborted(ImageReader src) {}
1755 }
1756
1757 private static Boolean isLinkedProfileDisabled = null;
1758
1759 private static boolean isLinkedProfileAllowed() {
1760 if (isLinkedProfileDisabled == null) {
1761 PrivilegedAction<Boolean> a = new PrivilegedAction<Boolean>() {
1762 public Boolean run() {
1763 return Boolean.getBoolean("sun.imageio.plugins.bmp.disableLinkedProfiles");
1764 }
1765 };
1766 isLinkedProfileDisabled = AccessController.doPrivileged(a);
1767 }
1768 return !isLinkedProfileDisabled;
1769 }
1770
1771 private static Boolean isWindowsPlatform = null;
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784 private static boolean isUncOrDevicePath(byte[] p) {
1785 if (isWindowsPlatform == null) {
1786 PrivilegedAction<Boolean> a = new PrivilegedAction<Boolean>() {
1787 public Boolean run() {
1788 String osname = System.getProperty("os.name");
1789 return (osname != null &&
1790 osname.toLowerCase().startsWith("win"));
1791 }
1792 };
1793 isWindowsPlatform = AccessController.doPrivileged(a);
1794 }
1795
1796 if (!isWindowsPlatform) {
1797
1798 return false;
1799 }
1800
1801
1802 if (p[0] == '/') p[0] = '\\';
1803 if (p[1] == '/') p[1] = '\\';
1804 if (p[3] == '/') p[3] = '\\';
1805
1806
1807 if ((p[0] == '\\') && (p[1] == '\\')) {
1808 if ((p[2] == '?') && (p[3] == '\\')) {
1809
1810 return ((p[4] == 'U' || p[4] == 'u') &&
1811 (p[5] == 'N' || p[5] == 'n') &&
1812 (p[6] == 'C' || p[6] == 'c'));
1813 } else {
1814
1815 return true;
1816 }
1817 } else {
1818 return false;
1819 }
1820 }
1821 }